package lianle

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"web_framework/config"
	"web_framework/pkg/e"
	"web_framework/pkg/errno"
	"web_framework/storage"

	log "github.com/sirupsen/logrus"
)

const (
	//RedisLianleAPITokenKEY token缓存键
	RedisLianleAPITokenKEY string = "router:lianle:token"
	//RedisLianleAPIVersionKEY 版本缓存
	RedisLianleAPIVersionKEY string = "router:lianle:version"
	//RedisLianleAPITokenExpire token缓存时间
	RedisLianleAPITokenExpire int = 7000
	// 版本缓存时间
	RedisLianleAPIVersionExpire int = 3600 * 12
	//APIDomain 练了API的请求domain
	APIDomain string = "http://i.lianle.com/AcinfoConfig/"
)

type response struct {
	Status string `json:"status,omitempty"`
	Info   string `json:"Info,omitempty"`
	Data   Data   `json:"data,omitempty"`
}

//Data 接口返回的data
type Data struct {
	Token        string `json:"token,omitempty"`
	Expires      int    `json:"expires_in,omitempty"`
	VersionFrom  string `json:"version_from,omitempty"`
	VersionTo    string `json:"version_to,omitempty"`
	AcID         string `json:"acid,omitempty"`
	SoftVersion  string `json:"soft_version,omitempty"`
	Online       string `json:"online,omitempty"`
	Sn           string `json:"sn,omitempty"`
	Mac          string `json:"mac,omitempty"`
	WifiEnable   string `json:"wifi_enable,omitempty"`
	SSIdName     string `json:"ssid_name,omitempty"`
	HideName     string `json:"hide_name,omitempty"`
	SecurityMode string `json:"security_mode,omitempty"`
	Key          string `json:"key,omitempty"`
}

// LianLeAPI 联乐API接口结构体

// 从缓存获取当前盛天版本号
func GetVersion(sn string) (string, error) {
	var VersionFrom string
	var err error
	hasCache := storage.RedisExists(RedisLianleAPIVersionKEY)
	if hasCache == false {
		data, err := STVersion(sn)
		if err != nil {
			return "", err
		}
		VersionFrom = data.VersionFrom
		_, err = storage.RedisSet(RedisLianleAPIVersionKEY, VersionFrom, RedisLianleAPIVersionExpire)
		if err != nil {
			return "", err
		}
	}else {
		VersionFrom, err = storage.RedisGet(RedisLianleAPIVersionKEY)
		if err != nil {
			return "", err
		}
	}
	return VersionFrom, nil
}

//从缓存中读取token,如果没有缓存则从重新请求
func GetTokenCache() (string, error) {
	var token string
	var err error
	hasCache := storage.RedisExists(RedisLianleAPITokenKEY)
	if hasCache {
		token, err = storage.RedisGet(RedisLianleAPITokenKEY)
		if err != nil {
			log.Info("TOKEN获取缓存失败")
			return "", err
		}
		if token != "" {
			return token, err
		}
	}

	token, err = GetToken()
	if err != nil {
		return "", err
	}
	_, err = storage.RedisSet(RedisLianleAPITokenKEY, token, RedisLianleAPITokenExpire)
	if err != nil {
		log.Info("TOKEN缓存失败")
		return "", err
	}

	return token, nil
}

//向盛天请求token
func GetToken() (string, error) {
	apiRoute := "token"
	data := make(map[string]string)
	data["account"] = config.C.Lianle.Account
	data["password"] = config.C.Lianle.Password
	data["sign"] = e.Md5Str("account="+config.C.Lianle.Account+"&password="+config.C.Lianle.Password+"&"+config.C.Lianle.Key)

	response, err := apiGet(apiRoute, data)
	if err != nil {
		return "", err
	}

	return response.Data.Token, err
}

//验证sn与mac合法性
func ValidateSN(sn string, mac string) (bool, error) {
	token, err := GetTokenCache()
	if err != nil {
		return false, err
	}
	data := map[string]string{
		"sn":    sn,
		"mac":   mac,
		"token": token,
	}
	//待盛天提供
	apiRoute := "TEST"
	if _, err := apiGet(apiRoute, data); err != nil {
		return false, err
	}

	return true, nil
}


// 2.1 更新设备信息
func STSettingUpdate(sn, SSidName, key, wifiEnable, securityMode string) error {

	token, err := GetTokenCache()
	if err != nil {
		return err
	}

	apiRoute := "settingUpdate"
	data := make(map[string]string)
	data["sn"] = sn
	data["wifi_enable"] = wifiEnable
	data["ssid_name"] = SSidName
	data["security_mode"] = securityMode
	data["token"] = token
	if key != "" {
		data["key"] = key
	}
	response, err := apiGet(apiRoute, data)
	if err != nil {
		return err
	}

	if response.Status == "error" {
		errno.ErrLianLe.Info = "调用盛天接口失败：" + response.Info
		log.Error(errno.ErrLianLe.Info)
		return errno.ErrLianLe
	}

	return nil
}

// 2.12.1 设备SN+Mac查询
func STDeviceInfo(sn, mac string) (Data, error) {
	var device Data
	token, err := GetTokenCache()
	if err != nil {
		return device, err
	}

	apiRoute := "deviceInfo"
	data := make(map[string]string)
	data["sn"] = sn
	data["mac"] = mac
	data["token"] = token
	response, err := apiGet(apiRoute, data)
	if err != nil {
		return device, err
	}

	if response.Status == "error" {
		errno.ErrLianLe.Info = "调用盛天接口失败：" + response.Info
		log.Error(errno.ErrLianLe.Info)
		return device, errno.ErrLianLe
	}
	device = response.Data

	return device, nil
}

// 2.12.2 设备SN查询接口
func STSnCheck(sn string) error {

	token, err := GetTokenCache()
	if err != nil {
		return err
	}

	apiRoute := "snCheck"
	data := make(map[string]string)
	data["sn"] = sn
	data["token"] = token
	response, err := apiGet(apiRoute, data)
	if err != nil {
		return err
	}

	if response.Status == "error" {
		errno.ErrLianLe.Info = "调用盛天接口失败：" + response.Info
		log.Error(errno.ErrLianLe.Info)
		return errno.ErrLianLe
	}
	return nil
}

// 2.12.3 升级版本号接口
func STVersion(sn string) (Data, error) {
	var device Data
	token, err := GetTokenCache()
	if err != nil {
		return device, err
	}

	apiRoute := "version"
	data := make(map[string]string)
	data["sn"] = sn
	data["token"] = token
	response, err := apiGet(apiRoute, data)
	if err != nil {
		return device, err
	}

	if response.Status == "error" {
		errno.ErrLianLe.Info = "调用盛天接口失败：" + response.Info
		log.Error(errno.ErrLianLe.Info)
		return device, errno.ErrLianLe
	}
	device = response.Data

	return device, nil
}


// 2.2.2 WIFI信息查询接口
func STWifiInfo(sn string) (Data, error) {

	var returnData Data
	token, err := GetTokenCache()
	if err != nil {
		return returnData, err
	}

	apiRoute := "settingShow"
	data := make(map[string]string)
	data["sn"] = sn
	data["token"] = token
	response, err := apiGet(apiRoute, data)
	if err != nil {
		return returnData, err
	}

	if response.Status == "error" {
		errno.ErrLianLe.Info = "调用盛天接口失败：" + response.Info
		log.Error(errno.ErrLianLe.Info)
		return returnData,errno.ErrLianLe
	}
	return response.Data,nil
}

// 2.10 重置密码
func STpwdUpdate(sn, oldPassword, newPassword string) error {

	// 是否需要调用盛天接口
	if oldPassword == newPassword {
		return nil
	}

	token, err := GetTokenCache()
	if err != nil {
		return err
	}

	apiRoute := "pwdUpdate"
	data := make(map[string]string)
	data["sn"] = sn
	data["token"] = token
	data["oldpassword"] = oldPassword
	data["newpassword"] = newPassword
	response, err := apiGet(apiRoute, data)
	if err != nil {
		return err
	}

	if response.Status == "error" {
		errno.ErrLianLe.Info = "调用盛天接口失败：" + response.Info
		log.Error(errno.ErrLianLe.Info)
		return errno.ErrLianLe
	}
	return nil
}

// 2.11 设备重启
func STWifiReboot(sn string) error {

	token, err := GetTokenCache()
	if err != nil {
		return err
	}

	apiRoute := "reboot"
	data := make(map[string]string)
	data["sn"] = sn
	data["token"] = token
	response, err := apiGet(apiRoute, data)
	if err != nil {
		return err
	}

	if response.Status == "error" {
		errno.ErrLianLe.Info = "调用盛天接口失败：" + response.Info
		log.Error(errno.ErrLianLe.Info)
		return errno.ErrLianLe
	}
	return nil
}


func apiGet(urlRouter string, args map[string]string) (response, error) {
	apiURL := APIDomain + urlRouter
	u, _ := url.Parse(apiURL)
	q := u.Query()
	for index, value := range args {
		q.Set(index, value)
	}
	u.RawQuery = q.Encode()
	res, err := http.Get(u.String())
	if err != nil {
		return response{}, err
	}
	var data response
	json.NewDecoder(res.Body).Decode(&data)
	res.Body.Close()
	if err != nil {
		return response{}, err
	}
	fmt.Printf("%+v\n", data)
	return data, nil
}
